<?php

namespace App\CLI;

class CConsole 
{
	
	private static $_ARGS=[];
	/**
	 * 输入交互
	 * @param unknown $message
	 * @param string $default
	 * @return boolean|string
	 */
	public static function prompt($message,$default=null)
	{
		if($default!==null)
			$message.=" \tdefault:[$default] ";
		else
			$message.=' ';
	
		if(extension_loaded('readline'))
		{
			$input=readline($message);
			if($input!==false)
				readline_add_history($input);
		}
		else
		{
			echo $message;
			$input=fgets(STDIN);
		}
	
		if($input===false)
			return false;
		else{
			$input=trim($input);
			return ($input==='' && $default!==null) ? $default : $input;
		}
	}
	
	/**
	 * 确认交互
	 * @param unknown $message
	 * @param string $default
	 * @return Ambigous <boolean, string>
	 */
	public static function confirm($message,$default=false)
	{
		echo $message.' (yes|no) [' . ($default ? 'yes' : 'no') . ']:';
	
		$input = trim(fgets(STDIN));
		return empty($input) ? $default : !strncasecmp($input,'y',1);
	}
	
	/**
	 * 格式化输出
	 * @param string $string_format
	 * @param array $params
	 */
	public static function print_line($string_format,$params=array())
	{
		if(count($params)<1)
		{
			echo $string_format;
		}
		else
		{
			echo str_replace(array_keys($params), array_values($params), $string_format);
		}
		echo "\n";
	}
	
	public static function run($args=[])
	{
		self::$_ARGS=$args;
		if(count($args)<1)
		{
			self::get_help();
		}
		else 
		{
			$base_class_name=array_shift($args);
			$class_name="\\App\\CLI\\".$base_class_name;
			self::try_to_include($base_class_name);	
			if(class_exists($class_name))
			{
				$runner=new $class_name();
				if(!($runner instanceof CLIRunner))
				{
					self::print_line("command `{{cmd}}` not support!",array('{{cmd}}'=>$class_name));
					self::get_help();
				}
				else
				{
					$runner->run($args);					
				}
			}
			else 
			{
				self::print_line("command `{{cmd}}` not found!",array('{{cmd}}'=>$class_name));
				self::get_help();
			}
		}	
	}

	public static function get_help()
	{
		self::print_line("Usage : php cli [cmd]");
		$commands = self::get_commands();
		asort($commands);
		$cmd_str = implode("\n\t ",$commands);
		self::print_line("can used cmd :\t\n\t {$cmd_str}");
	}	
	
	public static function get_commands()
	{
		$commands=[];
		$path=L_APP_PATH."CLI";		
		if(($handle = opendir($path)) != false)
		{
			while ( false !== ($file = readdir($handle)))
			{
					if( $file != "." && $file != ".." && $file!="CConsole.php" && file_exists($path."/".$file))
					{
					    $command = self::get_base_file_name($file);
					    if($command)
					    {
					        $commands[] = $command;
					    }
					}
			}
			closedir($handle);
		}	
		return $commands;
	}
		
	public static function get_base_file_name($full_name)
	{		
		if(strlen($full_name)<5 || substr($full_name,-4) !=".php")
		{
			return false;
		}		
		return substr($full_name,0,strlen($full_name)-4);
	}
	
	public static function try_to_include($class)
	{
		$file_path=L_APP_PATH."CLI/".$class.".php";		
		if(file_exists($file_path))
		{
			require_once ($file_path);
		}
	}
}

abstract class CLIRunner
{
	abstract protected function get_useful_actions();
	public function get_help()
	{
		CConsole::print_line("can used action:");
		$actions=$this->get_useful_actions();
		asort($actions);
		CConsole::print_line("-- can used action: \t\n {{action}}",array("{{action}}"=>implode(" \t\n ",$actions)));
	}
	
	public function run($args=[])
	{
		if(count($args)<1)
		{
			$this->get_help();
		}
		else
		{
			$action=array_shift($args);
			$method=$action."_action";
			if(method_exists($this, $method))
			{
				$res=call_user_func_array(array($this,$method), $args);
				echo json_encode($res,true);
				echo "\n";
			}
			else 
			{
				CConsole::print_line("can not found `{{method}}` action!",array('{{method}}'=>$action));
			}
		}
	}
}
